#include "PreViewProcess.h"
#include "Utils/LogUtil.h"
#include "Render/RenderState.h"
#include "Core/CoreGlobals.h"
#include "Game/Scene/Entity.h"
#include "Game/Component/Model.h"
#include "Render/Buffer/VertexBuffer.h"
#include "Render/Buffer/IndexBuffer.h"
#include "Render/Buffer/CustomBuffer.h"
#include "LocalShader.h"
#include "LocalScene.h"
#include "ResourceProcess.h"
#include "Shadows/ShadowsAtrousFilterProcess.h"
#include "Reflections/ReflectionsAtrousFilterProcess.h"

void PreViewProcess::OnInit()
{
	mLocalScene = static_cast<LocalScene*>(mGameScene);
	mResourceProcess = mLocalScene->GetProcess<ResourceProcess>("ResourceProcess");
	mShadowsAtrousFilterProcess = mLocalScene->GetProcess<ShadowsAtrousFilterProcess>("ShadowsAtrousFilterProcess");
	mReflectionsAtrousFilterProcess = mLocalScene->GetProcess<ReflectionsAtrousFilterProcess>("ReflectionsAtrousFilterProcess");

	ENQUEUE_RENDER_COMMAND(BuildModel)([this](VkCommandBuffer commandBuffer)
		{



#if 0
			mDescriptor = RHIDescriptor::Builder()
				.PushShader<PreViewVertexShader>()
				.PushShader<PreViewFragmentShader>()
				.SetDescriptorCount(0, 1)
				.Build();

			RefCountPtr<RHISampler> trilinearSampler = GetSampler("ResourceProcess", "trilinearSampler");

			RefCountPtr<RHITexture> inputImage = GetTexture("ReflectionsRayTraceProcess", "colorImage");

			mDescriptor->SetValue("inputImage", inputImage, trilinearSampler);
			mDescriptorMask[0] = mDescriptor->AllocateDescriptor();

#else

			mDescriptor = RHIDescriptor::Builder()
				.PushShader<PreViewVertexShader>()
				.PushShader<PreViewFragmentShader>()
				.SetDescriptorCount(0, 2)
				.Build();

			RefCountPtr<RHISampler> trilinearSampler = GetSampler("ResourceProcess", "trilinearSampler");
			std::array<RefCountPtr<RHITexture>, 2> inputImage;

			inputImage[0] = GetTexture("ReflectionsAtrousFilterProcess", "outputImage_s");
			inputImage[1] = GetTexture("ReflectionsAtrousFilterProcess", "outputImage_d");

			mDescriptor->SetValue("inputImage", inputImage[0], trilinearSampler);
			mDescriptorMask[0] = mDescriptor->AllocateDescriptor();

			mDescriptor->SetValue("inputImage", inputImage[1], trilinearSampler);
			mDescriptorMask[1] = mDescriptor->AllocateDescriptor();

#endif




			mColorRenderTarget = ColorRenderTarget::Builder()
				.SetUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
				.SetStoreOp(VK_ATTACHMENT_STORE_OP_STORE)
				.SetFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
				.Build(this, "ColorRenderTarget");

			mPipeline = GraphicsPipeline::Builder()
				.SetDescriptor(mDescriptor)
				.AddColorRenderTarget(mColorRenderTarget)
				.SetDstStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetDstAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.SetSrcStageMask(VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT)
				.SetSrcAccessMask(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT)
				.Build();

			mRenderPass = RHIRenderPass::Builder()
				.AddRenderTarget(mColorRenderTarget)
				.AddPipeline(mPipeline)
				.SetSrcStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
				.SetSrcAccessMask(VK_ACCESS_SHADER_READ_BIT)
				.SetDstStageMask(VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT)
				.SetDstAccessMask(VK_ACCESS_SHADER_READ_BIT)
				.Build();

			mFrameBuffer = RHIFrameBuffer::Builder()
				.SetRenderPass(mRenderPass)
				.Build();
		});
}

void PreViewProcess::OnTick(float deltaTime)
{

	ENQUEUE_RENDER_COMMAND(RecordCommand)([this](VkCommandBuffer commandBuffer)
		{

			VkRenderPassBeginInfo renderPassBeginInfo = mFrameBuffer->GetRenderPassBeginInfo();

			vkCmdBeginRenderPass(commandBuffer, &renderPassBeginInfo, VK_SUBPASS_CONTENTS_INLINE);

			vkCmdSetViewport(commandBuffer, 0, 1, &GRenderState->GetViewport());
			vkCmdSetScissor(commandBuffer, 0, 1, &GRenderState->GetScissor());

			vkCmdBindPipeline(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline->GetPipeline());

#if 0

			vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline->GetPipelineLayout(), 0, 1, &mDescriptorMask[0].GetDescriptorSet(), 0, nullptr);

#else

			vkCmdBindDescriptorSets(commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, mPipeline->GetPipelineLayout(), 0, 1, &mDescriptorMask[mReflectionsAtrousFilterProcess->mReadIndex].GetDescriptorSet(), 0, nullptr);

#endif

			vkCmdDraw(commandBuffer, 3, 1, 0, 0);

			vkCmdEndRenderPass(commandBuffer);
		});
}

void PreViewProcess::OnResize()
{

#if 0

	RefCountPtr<RHISampler> trilinearSampler = GetSampler("ResourceProcess", "trilinearSampler");

	RefCountPtr<RHITexture> inputImage = GetTexture("ReflectionsRayTraceProcess", "colorImage");

	mDescriptor->SetValue("inputImage", inputImage, trilinearSampler);
	mDescriptor->UpdateDescriptor(mDescriptorMask[0]);

#else

	RefCountPtr<RHISampler> trilinearSampler = GetSampler("ResourceProcess", "trilinearSampler");
	std::array<RefCountPtr<RHITexture>, 2> inputImage;

	inputImage[0] = GetTexture("ReflectionsAtrousFilterProcess", "outputImage_s");
	inputImage[1] = GetTexture("ReflectionsAtrousFilterProcess", "outputImage_d");

	mDescriptor->SetValue("inputImage", inputImage[0], trilinearSampler);
	mDescriptor->UpdateDescriptor(mDescriptorMask[0]);

	mDescriptor->SetValue("inputImage", inputImage[1], trilinearSampler);
	mDescriptor->UpdateDescriptor(mDescriptorMask[1]);

#endif

	mColorRenderTarget = ColorRenderTarget::Builder()
		.SetUsage(VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_SAMPLED_BIT)
		.SetStoreOp(VK_ATTACHMENT_STORE_OP_STORE)
		.SetFinalLayout(VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL)
		.Build(this, "ColorRenderTarget");

	mFrameBuffer = RHIFrameBuffer::Builder()
		.AddRenderTarget(mColorRenderTarget)
		.SetRenderPass(mRenderPass)
		.Build();


}
